<?php

namespace App\V3\V3_1\Services;

use App\V3\V3_1\Models\HcMaterielTypeModel;
use App\V3\V3_1\Models\MaterielClassModel;
use App\V3\V3_1\Models\MaterielProductContentModel;
use App\V3\V3_1\Models\MaterielsTypeModel;
use App\V3\V3_1\Models\MaterielTypeModel;
use App\V3\V3_1\Models\SellGoodsDetailModel;
use App\V3\V3_1\Models\SellModel;
use App\V3\V3_1\Models\StorageManageModel;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use OSS\OssClient;

class MaterielTypeService
{
    /**
     * 新建商品信息
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:43
     * @return array
     */
    static public function add($data)
    {
        if($data['is_product_materiel']) {
            unset($data['product_content']);
            $result = MaterielsTypeModel::insertGetId($data);
        }
        else {
            $result = ['code' => 0, 'msg' => 'success', 'data' => ['id' => MaterielsTypeModel::insertGetId($data)]];
        }

        return $result;
    }

    /**
     * 校验物料商品编号是否存在
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:35
     * @return bool
     */
    static public function checkNo($data)
    {
        $checkMaterielNo = MaterielsTypeModel::checkMaterielTypeRandCode($data);

        if(!empty($checkMaterielNo)) {
            return false;
        }
        else {
            return true;
        }
    }

    static public function checkRandNo($data)
    {
        $checkMaterielNo = MaterielsTypeModel::checkMaterielTypeCode($data);

        if(!empty($checkMaterielNo)) {
            return false;
        }
        else {
            return true;
        }
    }

    /**
     * 验证商品信息是否已存在
     * @param $data
     * AUTHOR  : Sun Wu
     * DateTime: 2022/3/4 15:41
     * @return bool
     */
    static public function checkMaterielInfo($data)
    {
        $checkMaterielInfo = MaterielsTypeModel::checkMaterielInfo($data);
        if(!empty($checkMaterielInfo)) {
            return false;
        }
        else {
            return true;
        }
    }

    //根据id检索商品信息是否已存在
    static public function checkMateriel($mainId, $id)
    {
        if(empty(MaterielsTypeModel::where(['id' => $id, 'main_id' => $mainId])->first()))
        {
            return false;
        }
        else {
            return true;
        }
    }

    //检查除自身外是否有相同的商品信息
    static public function checkMaterielInfoExceptself($data)
    {
        $checkMaterielTypeInfo = MaterielsTypeModel::where([
            'main_id' => $data['main_id'],
            'materiel_name' => $data['materiel_name'],
            'type_name' => $data['type_name'],
            'materiel_class_id' => $data['materiel_class_id'],
            'delete_flag' => 0,
        ])
            ->where('id', '!=', $data['id'])
            ->first();

        if(!empty($checkMaterielTypeInfo)) {
            return false;
        }
        else {
            return true;
        }
    }

    //获取指定商品详细信息
    static public function info($id)
    {
        return MaterielTypeModel::info($id);
    }

    //物料列表
    static public function materielTypeSelect($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel)
    {
        return MaterielsTypeModel::materielTypeSelect($mainId, $keyword, $condition, $pageSize, $currentPage, $isProductMateriel);
    }

    //物料列表-含库存信息

    static public function list($user, $data, $isProductMateriel)
    {
        $condition = [];
        if(!empty($data['materiel_class_id'])) {
            $condition['a.materiel_class_id'] = ['EQ' => $data['materiel_class_id']];
        }

        if(isset($data['is_product_class'])) {
            $condition['c.is_product_class'] = ['EQ' => $data['is_product_class']];
        }

        if(isset($data['is_product_materiel'])) {
            $condition['b.is_product_materiel'] = ['EQ' => $data['is_product_materiel']];
        }

        $keyword = empty($data['keyword'])?'':$data['keyword'];


        $typeId = [];
        if(!empty($data['type_id'])) {
            $typeId = array_filter(explode(',', $data['type_id']));
        }

        return MaterielsTypeModel::getMaterielTypeList($user, $condition, $keyword, $data, $typeId, $isProductMateriel);        
    }

    //修改成本价
    static public function editMaterielCost($data)
    {
        DB::beginTransaction();

        try {
            MaterielsTypeModel::where('id', $data['id'])->update(['cost' => $data['cost']]);
            StorageManageModel::where('type_id', $data['id'])->update(['materiel_mean_cost' => $data['cost']]);
            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('修改成本异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => ''];
        }
    }

    //新建套件
    public static function addProductMateriel(array $data)
    {
        $classInfo = MaterielClassModel::getProductClassInfo($data);

        if(empty($classInfo)) {
            return ['code' => 1, 'msg' => '商品类型与套件不匹配，请重试', 'data' => ''];
        }

        $productContent = json_decode($data['product_content'], true);

        DB::beginTransaction();

        try {
            $priceType = $data['price_type'];
            unset($data['price_type']);
            $materielTypeId = self::add($data);

            $arr = [];
            $sellPrice = 0;//原商品售价
            $price = 0;//改价后金额
            $hasSerialMateriel = 0;
            foreach($productContent as $value) {
                if(!isset($value['type_id']) || empty($value['type_id'])) {
                    return ['code' => 1, 'msg' => '请选择要添加的商品', 'data' => ''];
                }

                if($value['num'] < 0) {
                    return ['code' => 1, 'msg' => '套件内商品数量必须大于0', 'data' => ''];
                }

                if(!is_numeric($value['num'])) {
                    return ['code' => 1, 'msg' => '套件内商品数量仅能为数字', 'data' => ''];
                }

                if($value['price'] < 0) {
                    return ['code' => 1, 'msg' => '套件内商品单价必须大于0', 'data' => ''];
                }

                if(!is_numeric($value['price'])) {
                    return ['code' => 1, 'msg' => '套件内商品单价仅能为数字', 'data' => ''];
                }

                $price += $value['price'] * $value['num'];
                $sellPrice += $value['selling_price'] * $value['num'];

                $materielInfo = MaterielTypeModel::where('id', $value['type_id'])->first();

                if($materielInfo['is_use_serial']) {
                    $hasSerialMateriel = 1;
                }
            }

            $totalPrice = 0;
            $isUp = 0;
            $discount = 0;
            $calcRatio = 0;
            if($priceType) {
                foreach($productContent as $val) {
                    $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                    //是否溢价
                    if($data['selling_price'] > $price) {
                        $isUp = 1;
                        $discount = substr((($data['selling_price'] - $price) / $price), 0, 4);
                        $newPrice = ($val['price'] * $discount) + $val['price'];
                        $calcRatio = sprintf('%.2f', ($data['selling_price'] / $price));
                    }
                    else {
                        $isUp = 0;
                        $discount = substr(($price / $sellPrice), 0, 4);
                        $newPrice = $val['price'] * $discount;
                        $calcRatio = sprintf('%.2f', ($sellPrice / $price));
                    }

                    $arr[] = [
                        'main_id' => $data['main_id'],
                        'type_id' => $val['type_id'],
                        'price' => sprintf('%.6f', $newPrice),
                        'origin_price' => $val['selling_price'],
                        'is_use_serial' => $typeInfo['is_use_serial'],
                        'total_price' => sprintf('%.6f', ($newPrice * $val['num'])),
                        'product_id' => $materielTypeId,
                        'num' => $val['num'],
                        'created_at' => time()
                    ];

                    $totalPrice += sprintf('%.6f', ($newPrice * $val['num']));
                }

                MaterielsTypeModel::where('id', $materielTypeId)
                    ->update([
                        'selling_price' => $data['selling_price'],
                        'ratio' => $discount,
                        'price_up_or_down' => $isUp,
                        'calc_ratio' => $calcRatio,
                    ]);
            }
            else {
                foreach($productContent as $val) {
                    $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                    $arr[] = [
                        'main_id' => $data['main_id'],
                        'type_id' => $val['type_id'],
                        'price' => sprintf('%.6f', $val['price']),
                        'total_price' => sprintf('%.6f', ($val['price'] * $val['num'])),
                        'origin_price' => $val['selling_price'],
                        'is_use_serial' => $typeInfo['is_use_serial'],
                        'product_id' => $materielTypeId,
                        'num' => $val['num'],
                        'created_at' => time()
                    ];

                    $totalPrice += sprintf('%.6f', ($val['price'] * $val['num']));
                }

                MaterielsTypeModel::where('id', $materielTypeId)
                    ->update(['selling_price' => $price]);
            }

            MaterielProductContentModel::insert($arr);

            if($priceType) {
                $balance = $data['selling_price'] - $totalPrice;

                $firstData = MaterielProductContentModel::where('product_id', $materielTypeId)
                    ->first();

                MaterielProductContentModel::where('id', $firstData['id'])
                    ->update([
                        'price' => DB::raw('price +' . ($balance / 10)),
                        'total_price' => DB::raw('total_price +' . $balance)
                    ]);
            }

            //若套件为存在开启了序列号的商品，则套餐标记为必须开启序列号
            MaterielTypeModel::where('id', $materielTypeId)
                ->update(['is_use_serial' => $hasSerialMateriel]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ['id' => $materielTypeId]];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('添加套件异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '添加套件异常', 'data' => ''];
        }
    }

    public static function editMateriel(array $data)
    {
        unset($data['product_content']);
        unset($data['price_type']);
        unset($data['is_product_materiel']);
        DB::beginTransaction();

        try {
            //检查物料商品编号是否存在
//            $checkNo = MaterielTypeService::checkRandNo($data);
//            if(!$checkNo) {
//                return ['code' => 1, 'msg' => '商品编号已存在，请重新输入', 'data' => ''];
//            }

            //验证商品信息除己身外是否已存在
            $checkMaterielInfo = MaterielTypeService::checkMaterielInfoExceptself($data);
            if(!$checkMaterielInfo) {
                return ['code' => 1, 'msg' => '物料类型`'.$data['materiel_name'].'-'.$data['type_name'].'`已存在', 'data' => ''];
            }

            $materielTypeInfo = MaterielsTypeModel::where('id', $data['id'])->first();
            if(!empty($materielTypeInfo['materiel_img'])) {
                $client = new OssClient(
                    config('app.aliyun_oss_key'),
                    config('app.aliyun_oss_secret'),
                    config('app.aliyun_oss_endpoint'),
                );

                $isHttpStart = substr($materielTypeInfo['materiel_img'], 0, 4);

                if($isHttpStart != 'http') {
                    if(file_exists(public_path().$materielTypeInfo['materiel_img'])) {
                        unlink(public_path().$materielTypeInfo['materiel_img']);
                    }
                }
                else {
                    $substrUrl = explode('uploads', $materielTypeInfo['materiel_img']);

                    $client->deleteObject(config('app.aliyun_oss_bucket'), 'uploads'.$substrUrl[1]);
                }
            }

            MaterielsTypeModel::where('id', $data['id'])->update($data);

            $storageManageInfo = StorageManageModel::where('type_id', $data['id'])->where('delete_flag', 0)->first();
            if(!empty($storageManageInfo)) {
                $storageManageInfo->materiel_mean_cost = $data['cost'];
                $storageManageInfo->save();
            }

//            unset($data['materiel_thumbnail_img']);

            HcMaterielTypeModel::where(['id'=>$data['id'],'main_id'=>$data['main_id']])->update($data);
            StorageManageModel::where('type_id', $data['id'])->update([
                'materiel_mean_cost' => $data['cost']
            ]);

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('编辑商品信息异常'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '编辑商品信息异常', 'data' => ''];
        }
    }

    public static function editProductMateriel(array $data)
    {
        $newData = $data;
        unset($newData['product_content']);

        $priceType = $data['price_type'];
        unset($data['price_type']);

        $productContent = json_decode($data['product_content'], true);

        $info = MaterielTypeModel::where('id', $data['id'])->first();

       /*  if($info['product_use_tag']) {
            return ['code' => 1, 'msg' => '目标套餐商品已被使用，无法进行编辑', 'data' => ''];
        } */

        self::editMateriel($newData);
        if($info['product_use_tag']) {
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }else{
        try {
            MaterielProductContentModel::where('product_id', $data['id'])->delete();

            $sellPrice = 0;
            $price = 0;
            $arr = [];
            foreach($productContent as $value) {
                if(!isset($value['type_id']) || empty($value['type_id'])) {
                    return ['code' => 1, 'msg' => '请选择要添加的商品', 'data' => ''];
                }

                if($value['num'] < 0) {
                    return ['code' => 1, 'msg' => '套件内商品数量必须大于0', 'data' => ''];
                }

                if(!is_numeric($value['num'])) {
                    return ['code' => 1, 'msg' => '套件内商品数量仅能为数字', 'data' => ''];
                }

                if($value['price'] < 0) {
                    return ['code' => 1, 'msg' => '套件内商品单价必须大于0', 'data' => ''];
                }

                if(!is_numeric($value['price'])) {
                    return ['code' => 1, 'msg' => '套件内商品单价仅能为数字', 'data' => ''];
                }

                $sellPrice += $value['selling_price'] * $value['num'];
                $price += $value['price'] * $value['num'];
            }

            $totalPrice = 0;
            $isUp = 0;
            $discount = 0;
            $calcRatio = 0;
            if($priceType) {
                foreach($productContent as $val) {
                    if($data['selling_price'] > $price) {
                        $isUp = 1;
                        $discount = substr((($data['selling_price'] - $price) / $price), 0, 4);
                        $newPrice = ($val['price'] * $discount) + $val['price'];
                        $calcRatio = sprintf('%.2f', ($data['selling_price'] / $price));
                    }
                    else {
                        $discount = substr(($price / $sellPrice), 0, 4);
                        $newPrice = $val['price'] * $discount;
                        $calcRatio = $sellPrice / $price;
                        $calcRatio = sprintf('%.2f', ($sellPrice / $price));
                    }

                    $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                    $arr[] = [
                        'main_id' => $data['main_id'],
                        'type_id' => $val['type_id'],
                        'price' => sprintf('%.6f', $newPrice),
                        'origin_price' => ($val['selling_price']),
                        'is_use_serial' => $typeInfo['is_use_serial'],
                        'total_price' => sprintf('%.6f', ($newPrice * $val['num'])),
                        'product_id' => $data['id'],
                        'num' => $val['num'],
                        'created_at' => time()
                    ];

                    $totalPrice += sprintf('%.6f', ($newPrice * $val['num']));
                }

                MaterielsTypeModel::where('id', $data['id'])
                    ->update([
                        'selling_price' => $data['selling_price'],
                        'ratio' => $discount,
                        'price_up_or_down' => $isUp,
                        'calc_ratio' => $calcRatio,
                    ]);
            }
            else {
                foreach($productContent as $val) {
                    $typeInfo = MaterielTypeModel::where('id', $val['type_id'])->first();

                    $arr[] = [
                        'main_id' => $data['main_id'],
                        'type_id' => $val['type_id'],
                        'price' => sprintf('%.6f', $val['price']),
                        'total_price' => sprintf('%.6f', ($val['price'] * $val['num'])),
                        'origin_price' => ($val['selling_price']),
                        'is_use_serial' => $typeInfo['is_use_serial'],
                        'product_id' => $data['id'],
                        'num' => $val['num'],
                        'created_at' => time()
                    ];

                    $totalPrice += sprintf('%.6f', ($val['price'] * $val['num']));
                }

                MaterielsTypeModel::where('id', $data['id'])
                    ->update(['selling_price' => $price]);
            }

            MaterielProductContentModel::insert($arr);

            if($priceType) {
                $balance = $data['selling_price'] - $totalPrice;

                $firstData = MaterielProductContentModel::where('product_id', $data['id'])
                    ->first();

                MaterielProductContentModel::where('id', $firstData['id'])
                    ->update([
                        'price' => DB::raw('price +' . ($balance / 10)),
                        'total_price' => DB::raw('total_price +' . $balance)
                    ]);
            }

            DB::commit();
            return ['code' => 0, 'msg' => 'success', 'data' => ''];
        }
        catch(Exception $e) {
            DB::rollBack();
            Log::debug('编辑套件异常:'.var_export($e->getMessage(), true));
            return ['code' => 1, 'msg' => '编辑套件信息异常', 'data' => ''];
        }
        }
    }

    public static function packageInfo(array $data)
    {
        $materielProductContentInfo = MaterielProductContentModel::select(
            'a.*',
            'materiel_name',
            'type_name',
            'materiel_unit',
            'materiel_img'
        )
            ->where([
                'product_id' => $data['id']
            ])
            ->from('materiel_product_content as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->get()->toArray();

        if(!empty($data['sell_id'])) {
            $sellInfo = SellGoodsDetailModel::where([
                'sell_id' => $data['sell_id'],
                'materiel_type_id' => $data['id'],
                'is_product_materiel' => 1
            ])->first();

            if(empty($sellInfo)) {
                return ['code' => 1, 'msg' => '类型错误，暂无内容', 'data' => ''];
            }

            $price = 0;
            $totalPrice = 0;
            foreach($materielProductContentInfo as &$value) {
                $value['price'] = $value['price'] * $sellInfo['calc_ratio'];
                $value['total_price'] = $value['total_price'] * $sellInfo['calc_ratio'];

                $price += $value['price'];
                $totalPrice += $value['total_price'];
            }

            if($sellInfo['price'] > $totalPrice) {//补足
                $balance = $sellInfo['price'] - $totalPrice;

                $materielProductContentInfo[0]['price'] += $balance;
                $materielProductContentInfo[0]['total_price'] += $balance;
            }
            else {//抵扣
                $balance = $totalPrice - $sellInfo['price'];

                //对套件按价格降序排列
                usort($materielProductContentInfo, function($a, $b) {
                    if($a['price'] == $b['price']) {
                        return 0;
                    }

                    return ($a['price'] > $b['price'])?-1:1;
                });

                $materielProductContentInfo[0]['price'] -= $balance;
                $materielProductContentInfo[0]['total_price'] -= $balance;
            }
        }

        return $materielProductContentInfo;
    }

    public static function updateProductInfo(array $data)
    {
        DB::beginTransaction();

        try {
            if(!$data['is_product_materiel']) {
                //获取目标商品相关的所有套餐信息
                $productContentInfo = MaterielProductContentModel::where('type_id', $data['id'])->get()->toArray();

                if(!empty($productContentInfo)) {
                    //更新目标商品在套餐商品表中的序列号开启状态
                    MaterielProductContentModel::where('type_id', $data['id'])->update(['is_use_serial' => $data['is_use_serial']]);

                    $productId = [];
                    foreach($productContentInfo as $contentVal) {
                        $productId[] = $contentVal['product_id'];
                    }
                    
                    if(!empty($productId)) {
                        $productId = array_unique($productId);
                        //检查已使用目标商品的套餐是否仍存在使用已开启序列号商品的情况
                        $checkProductInfo = MaterielProductContentModel::where('is_use_serial', 1)
                            ->whereIn('product_id', $productId)->get()->toArray();

                        if(empty($checkProductInfo)) {
                            MaterielTypeModel::where('is_product_materiel', 1)
                                ->whereIn('id', $productId)
                                ->update(['is_use_serial' => 0]);
                        }
                        else {
                            MaterielTypeModel::where('is_product_materiel', 1)
                                ->whereIn('id', $productId)
                                ->update(['is_use_serial' => 1]);
                        }
                    }
                }
            }

            DB::commit();
            return true;
        }
        catch(Exception $e) {
            DB::rollBack();
            return ['code' => 1, 'msg' => '编辑商品信息失败，请重试', 'data' => ''];
        }
    }
}
